 ;(function($, window, document, undefined)
		 { 
		     var hasTouch = 'ontouchstart' in document;
		     var hasPointerEvents = (function()
		     {   
		         var el    = document.createElement('div'),
		             docEl = document.documentElement;
		         if (!('pointerEvents' in el.style)) {
		             return false;
		         }
		         el.style.pointerEvents = 'auto';
		         el.style.pointerEvents = 'x';
		         docEl.appendChild(el);
		         var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';
		         docEl.removeChild(el);
		         return !!supports;
		     })();

		     var defaults = {
		         listNodeName    : 'ol',
		         itemNodeName    : 'li',
		         rootClass       : 'dd',
		         listClass       : 'dd-list',
		         itemClass       : 'dd-item',
		         dragClass       : 'dd-dragel',
		         handleClass     : 'dd-handle',
		         collapsedClass  : 'dd-collapsed',
		         placeClass      : 'dd-placeholder',
		         noDragClass     : 'dd-nodrag',
		         emptyClass      : 'dd-empty',
		         expandBtnHTML   : '<button data-action="expand" type="button">展开</button>',
		         collapseBtnHTML : '<button data-action="collapse" type="button">关闭</button>',
		         group           : 0,
		         maxDepth        : 5,
		         threshold       : 20
		     };
		  

		     function Plugin11(element, options)
		     {
		         this.w  = $(document);
		         this.el = $(element);
		         this.options = $.extend({}, defaults, options);
		         this.init();
		     }

		     Plugin11.prototype = {
		         init: function()
		         {   
		             var list = this;

		             list.reset();

		             list.el.data('nestable-group', this.options.group);

		             list.placeEl = $('<div class="' + list.options.placeClass + '"/>');

		             $.each(this.el.find(list.options.itemNodeName), function(k, el) {
		                 list.setParent($(el));
		             });

		             list.el.on('click', 'button', function(e) {
		                 if (list.dragEl) {
		                     return;
		                 }
		                 var target = $(e.currentTarget),
		                     action = target.data('action'),
		                     item   = target.parent(list.options.itemNodeName);
		                 if (action === 'collapse') {
		                     list.collapseItem(item);
		                 }
		                 if (action === 'expand') {
		                     list.expandItem(item);
		                 }
		             });

		             var onStartEvent = function(e)
		             {
		                 var handle = $(e.target);
		                 if (!handle.hasClass(list.options.handleClass)) {
		                     if (handle.closest('.' + list.options.noDragClass).length) {
		                         return;
		                     }
		                     handle = handle.closest('.' + list.options.handleClass);
		                 }

		                 if (!handle.length || list.dragEl) {
		                     return;
		                 }

		                 list.isTouch = /^touch/.test(e.type);
		                 if (list.isTouch && e.touches.length !== 1) {
		                     return;
		                 }

		                 e.preventDefault();
		                 list.dragStart(e.touches ? e.touches[0] : e);
		             };

		             var onMoveEvent = function(e)
		             {
		                 if (list.dragEl) {
		                     e.preventDefault();
		                     list.dragMove(e.touches ? e.touches[0] : e);
		                 }
		             };

		             var onEndEvent = function(e)
		             {
		                 if (list.dragEl) {
		                     e.preventDefault();
		                     list.dragStop(e.touches ? e.touches[0] : e);
		                 }
		             };

		             if (hasTouch) {
		                 list.el[0].addEventListener('touchstart', onStartEvent, false);
		                 window.addEventListener('touchmove', onMoveEvent, false);
		                 window.addEventListener('touchend', onEndEvent, false);
		                 window.addEventListener('touchcancel', onEndEvent, false);
		             }

		             list.el.on('mousedown', onStartEvent);
		             list.w.on('mousemove', onMoveEvent);
		             list.w.on('mouseup', onEndEvent);

		         },

		         serialize: function()
		         {
		             var data,
		                 depth = 0,
		                 list  = this;
		             step  = function(level, depth)
		             {
		                 var array = [ ],
		                     items = level.children(list.options.itemNodeName);
		                 items.each(function()
		                 {
		                     var li   = $(this),
		                         item = $.extend({}, li.data()),
		                         sub  = li.children(list.options.listNodeName);
		                     if (sub.length) {
		                         item.children = step(sub, depth + 1);
		                     }
		                     array.push(item);
		                 });
		                 return array;
		             };
		             data = step(list.el.find(list.options.listNodeName).first(), depth);
		             return data;
		         },

		         serialise: function()
		         {
		             return this.serialize();
		         },

		         reset: function()
		         {
		             this.mouse = {
		                 offsetX   : 0,
		                 offsetY   : 0,
		                 startX    : 0,
		                 startY    : 0,
		                 lastX     : 0,
		                 lastY     : 0,
		                 nowX      : 0,
		                 nowY      : 0,
		                 distX     : 0,
		                 distY     : 0,
		                 dirAx     : 0,
		                 dirX      : 0,
		                 dirY      : 0,
		                 lastDirX  : 0,
		                 lastDirY  : 0,
		                 distAxX   : 0,
		                 distAxY   : 0
		             };
		             this.isTouch    = false;
		             this.moving     = false;
		             this.dragEl     = null;
		             this.dragRootEl = null;
		             this.dragDepth  = 0;
		             this.hasNewRoot = false;
		             this.pointEl    = null;
		         },

		         expandItem: function(li)
		         {
		             li.removeClass(this.options.collapsedClass);
		             li.children('[data-action="expand"]').hide();
		             li.children('[data-action="collapse"]').show();
		             li.children(this.options.listNodeName).show();
		         },

		         collapseItem: function(li)
		         {
		             var lists = li.children(this.options.listNodeName);
		             if (lists.length) {
		                 li.addClass(this.options.collapsedClass);
		                 li.children('[data-action="collapse"]').hide();
		                 li.children('[data-action="expand"]').show();
		                 li.children(this.options.listNodeName).hide();
		             }
		         },

		         expandAll: function()
		         {
		             var list = this;
		             list.el.find(list.options.itemNodeName).each(function() {
		                 list.expandItem($(this));
		             });
		         },

		         collapseAll: function()
		         {
		             var list = this;
		             list.el.find(list.options.itemNodeName).each(function() {
		                 list.collapseItem($(this));
		             });
		         },

		         setParent: function(li)
		         {  
		         	 
		             if (li.children(this.options.listNodeName).length) {
		                 li.prepend($(this.options.expandBtnHTML));
		                 li.prepend($(this.options.collapseBtnHTML));
		             }
		             li.children('[data-action="collapse"]').hide();
		         },

		         unsetParent: function(li)
		         {
		             li.removeClass(this.options.collapsedClass);
		             li.children('[data-action]').remove();
		             li.children(this.options.listNodeName).remove();
		         },
		     };

		     $.fn.nestable = function(params)
		     {   

		         var lists  = this,
		             retval = this;

		         lists.each(function()
		         {
		             var plugin = $(this).data("nestable");

		             if (!plugin) {
		                 $(this).data("nestable", new Plugin(this, params));
		                 $(this).data("nestable-id", new Date().getTime());
		             } else {
		                 if (typeof params === 'string' && typeof plugin[params] === 'function') {
		                     retval = plugin[params]();
		                 }
		             }
		         });

		         return retval || lists;
		     };
		    
		 })(window.jQuery || window.Zepto, window, document);

